/*
 * Copyright 2007. Mount Sinai Hospital, Toronto, Canada.
 * 
 * Licensed under the GNU Lesser General Public License, Version 2. You
 * can find a copy of the license at:
 * 
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
 * 
 * IN NO EVENT SHALL MOUNT SINAI HOSPITAL BE LIABLE TO ANY PARTY FOR DIRECT, 
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST 
 * PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
 * EVEN IF MOUNT SINAI HOSPITAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE.
 * 
 * MOUNT SINAI HOSPITAL SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND 
 * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". 
 * MOUNT SINAI HOSPITAL HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
 */
package com.sinai.mshab.client.ui.aggregate;

import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sinai.mshab.client.ui.FormComponent;
import com.sinai.mshab.client.ui.Key;
import com.sinai.mshab.client.ui.basic.CloneNotifierButton;
import com.sinai.mshab.client.ui.basic.NotifierButton;
import com.sinai.mshab.client.ui.basic.RemoveNotifierButton;

public class DynamicVerticalComponentList extends VerticalComponentList {

	/**
	 * The CSS style for headers (names) of columns. This is combined with
	 * headerCount to make a unique CSS style name.
	 */
	private static final String HEADER_STYLE = "mshab-DynamicVerticalComponentListHeader";

	/**
	 * The CSS style for the row of this dynamic list.
	 */
	private static final String ROW_STYLE = "mshab-DynamicVerticalComponentListRow";

	/**
	 * The CSS style for headers (names) of columns when they are in reports.
	 */
	private static final String HEADER_REPORT_STYLE = "mshab-"
			+ "DynamicVerticalComponentListHeaderReport";

	/**
	 * Keeps track of the number of headers. Used to create a unique CSS style.
	 */
	private int headerCount = 0;

	/**
	 * The panel that contains the contents of the growing row.
	 */
	protected HorizontalComponentList hPanel;

	/**
	 * The header that appears at the top of growing list.
	 */
	private HorizontalPanel header;

	private String newRowText;

	public DynamicVerticalComponentList(String tableName, String newRowText) {
		super(tableName, null, null, null, true);
		addDynamic(tableName, newRowText, null, null, null, true);
	}

	public DynamicVerticalComponentList(String tableName, String newRowText,
			boolean vertical) {
		super(tableName, null, null, null, vertical);
		addDynamic(tableName, newRowText, null, null, null, vertical);
	}

	public DynamicVerticalComponentList(String tableName, String newRowText,
			String description) {
		super(tableName, description, null, null, true);
		addDynamic(tableName, newRowText, description, null, null, true);
	}

	public DynamicVerticalComponentList(String tableName, String newRowText,
			String description, boolean vertical) {
		super(tableName, description, null, null, vertical);
		addDynamic(tableName, newRowText, description, null, null, vertical);
	}

	public DynamicVerticalComponentList(String tableName, String newRowText,
			String description, String quantifier) {
		super(tableName, description, quantifier, null, true);
		addDynamic(tableName, newRowText, description, quantifier, null, true);
	}

	public DynamicVerticalComponentList(String tableName, String newRowText,
			String description, String quantifier, boolean vertical) {
		super(tableName, description, quantifier, null, vertical);
		addDynamic(tableName, newRowText, description, quantifier, null,
				vertical);
	}

	public DynamicVerticalComponentList(String tableName, String newRowText,
			String description, String quantifier, String error_msg) {
		super(tableName, description, quantifier, error_msg, true);
		addDynamic(tableName, newRowText, description, quantifier, error_msg,
				true);
	}

	public DynamicVerticalComponentList(String tableName, String newRowText,
			String description, String quantifier, String error_msg,
			boolean vertical) {
		super(tableName, description, quantifier, error_msg, vertical);
		addDynamic(tableName, newRowText, description, quantifier, error_msg,
				vertical);
	}

	private void addDynamic(String tableName, String newRowText,
			String description, String quantifier, String error_msg,
			boolean vertical) {

		hPanel = new HorizontalComponentList();
		hPanel.addNotifyingComponent(new CloneNotifierButton(newRowText));
		hPanel.setStyleName(ROW_STYLE);
		hPanel.setCollect_sub_info(true);
		this.newRowText = newRowText;
		super.add(hPanel);
	}

	/**
	 * Adds another {@link FormComponent} that will grow dynamically.
	 * 
	 * @param widget
	 *            the widget to add.
	 */
	public void add(FormComponent widget) {

		// add the widget just above the notifier button.
		hPanel.add(widget, hPanel.getWidgetCount() - hPanel.notifierCount());
	}

	/**
	 * Adds another {@link FormComponent} that will grow dynamically. headerName
	 * will be added as the header for this column.
	 * 
	 * @param widget
	 *            the widget to add.
	 * @param headerName
	 *            the name of the column under widget widget resides.
	 */
	public void add(FormComponent widget, String headerName) {

		// add the widget just above the notifier button.
		hPanel.add(widget, hPanel.getWidgetCount() - 1);
		addHeader(headerName);
	}

	/**
	 * Appends a header to this DynamicVerticalComponentList. If no headers
	 * existed before, a new one is created and inserted as the first element of
	 * the DynamicVerticalComponentList.
	 * 
	 * @param newHeader
	 *            a new header to add.
	 */
	public void addHeader(String newHeader) {

		// instantiate if needed
		if (header == null) {
			header = new HorizontalPanel();
		}

		Label headerLabel = new Label(newHeader);
		headerLabel.setStyleName(HEADER_STYLE + headerCount + tableName);

		// add new label.
		header.add(headerLabel);

		// insure header is in the VerticalComponentList.
		super.insert(header, 0);

		// increase the header count.
		headerCount++;
	}

	/**
	 * Returns the list of headers in a String array.
	 * 
	 * @return the list of headers in a String array.
	 */
	public String[] getHeaders() {

		String[] result = null;

		if (header != null) {

			// make a new String[] the size of the number of widgets in header.
			result = new String[header.getWidgetCount()];

			// add the label's text to the String array.
			for (int i = 0; i < result.length; i++) {
				Label l = (Label) header.getWidget(i);
				result[i] = l.getText();
			}
		}

		return result;
	}

	/**
	 * Returns the header of this DynamicVerticalComponentList.
	 * 
	 * @return the header of this DynamicVerticalComponentList.
	 */
	public HorizontalPanel getHeader() {
		return header;
	}

	/**
	 * Removes the header with the label, <code>name</code>.
	 * 
	 * @param name
	 *            the label that marks the header.
	 */
	public void removeHeader(String name) {
		for (int i = 0; i < header.getWidgetCount(); i++) {
			Label l = (Label) header.getWidget(i);
			if (name.equals(l.getText())) {
				header.remove(i);
			}
		}
	}

	public VerticalPanel toReport() {

		// get super's report
		VerticalPanel report = super.toReport();

		if (header != null) {
			// make the header of the report.
			HorizontalPanel reportForHeader = new HorizontalPanel();
			reportForHeader.setStyleName(HEADER_REPORT_STYLE);

			// insert it after the description label (which is at index 0).
			report.insert(reportForHeader, 1);

			// copy the labels in report over.
			for (int i = 0; i < header.getWidgetCount(); i++) {
				Label headerElement = (Label) header.getWidget(i);
				reportForHeader.add(new Label(headerElement.getText()));
			}
		}

		return report;
	}

	/**
	 * Recieve a notification from contained component, clone it and add the
	 * clone one index below the <code>who</code>.
	 * 
	 * @param who
	 *            the <code>QuestionComposite</code> that notifies this
	 *            <code>VerticalComponentList</code>.
	 */
	public void receiveNotification(FormComponent who, FormComponent originator) {

		// let the super function do it's thing.
		super.receiveNotification(who, originator);

		// find the clone
		int index = vertical_panel.getWidgetIndex(who);
		Widget hpanel = vertical_panel.getWidget(index + 1);

		// if clone has no remove button, add it.
		if (hpanel instanceof HorizontalComponentList) {
			HorizontalComponentList panel = (HorizontalComponentList) hpanel;
			if (!panel.hasRemoveButtons()) {
				panel.addNotifyingComponent(new RemoveNotifierButton("Remove"));
			}
		}

		// if the number of widgets hit 1, remove any 'Remove' buttons.
		int count = vertical_panel.getWidgetCount();
		System.out.println("There are " + count + " elements");
		if (count == 1) {
			hpanel = vertical_panel.getWidget(0);
			if (hpanel instanceof HorizontalComponentList) {

				// remove all remove buttons
				HorizontalComponentList panel = (HorizontalComponentList) hpanel;
				panel.removeRemoveButtons();

				// add a clone button if neccessary
				if (!panel.hasCloneButtons()) {
					panel.addNotifyingComponent(new CloneNotifierButton(
							newRowText));
				}

			}
		}
		// else make sure the lowest hpanel in the list has a clone button
		else {
			hpanel = vertical_panel.getWidget(count - 1);
			if (hpanel instanceof HorizontalComponentList) {

				// remove all remove buttons
				HorizontalComponentList panel = (HorizontalComponentList) hpanel;
	
				// add a clone button if neccessary
				if (!panel.hasCloneButtons()) {
					panel.addNotifyingComponent(new CloneNotifierButton(
							newRowText), panel.getWidgetCount() - 1);
				}
			}
		}
	}
}
